<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Transformations</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Java2D, Java, tutorial, transformations, programming, graphics, multiplatform">
<meta name="description" content="In this part of the Java 2D tutorial, we work with transformations.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>


<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Transformations</h1>


<p>
In this part of the Java 2D programming tutorial, we will talk about 
transformations.
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
An <b>affine transform</b> is composed of zero or more 
linear transformations (rotation, scaling or shear) and translation (shift). 
Several linear transformations can be combined into a single matrix. 
A rotation is a transformation that moves a rigid body around a fixed point. 
A scaling is a transformation that enlarges or diminishes objects. 
The scale factor is the same in all directions. A translation is a transformation 
that moves every point a constant distance in a specified direction. A shear is a 
transformation that moves an object perpendicular to a given axis, with greater 
value on one side of the axis than the other. 
sources: (wikipedia.org, freedictionary.com)
</p>

<p>
The <code>AffineTransform</code> is the class in Java 2D to 
perform affine transformations. 
</p>


<h2>Translation</h2>

<p>
The following example describes a simple translation.
</p>

<div class="codehead">Translation.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Color;
import java.awt.Graphics;

import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Translation extends JPanel {

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(new Color(150, 150, 150));
        g2d.fillRect(20, 20, 80, 50);
        g2d.translate(150, 50);
        g2d.fillRect(20, 20, 80, 50);

    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Translation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Translation());
        frame.setSize(300, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
The example draws a rectangle. Then we do a translation and draw the same rectangle again.
</p>

<pre class="explanation">
g2d.translate(150, 50);
</pre>

<p>
This line moves the origin of the <b>Graphics2D</b> context to a new point. 
</p>

<img src="/img/gfx/java2d/translation.png" alt="Translation">
<div class="figure">Figure: Translation</div>

<h2>Rotation</h2>

<p>
The next example demonstrates a rotation.
</p>

<div class="codehead">Rotate.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Rotate extends JPanel {

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(new Color(150, 150, 150));
        g2d.fillRect(20, 20, 80, 50);
        g2d.translate(180, -50);
        g2d.rotate(Math.PI/4);
        g2d.fillRect(80, 80, 80, 50);

    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Rotation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Rotate());
        frame.setSize(300, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
The example draws a rectangle, performs a translation and a rotation 
and draws the same rectangle again.
</p>

<pre class="explanation">
g2d.rotate(Math.PI/4);
</pre>

<p>
The <code>rotate()</code> method performs rotation. Note 
that the rotation parameter is in radians.
</p>


<img src="/img/gfx/java2d/rotation.png" alt="Rotation">
<div class="figure">Figure: Rotation</div>


<h2>Scale</h2>

<p>
The next example demonstrates scaling of an object. Scaling is done 
with the <code>scale()</code> method.
In this method, we provide two parameters. They are the x scale and 
y scale factor, by which coordinates are scaled
along the x or y axis respectively
</p>

<div class="codehead">Scale.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Scale extends JPanel {

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(new Color(150, 150, 150));
        g2d.fillRect(20, 20, 80, 50);

        AffineTransform tx1 = new AffineTransform();
        tx1.translate(110, 22);
        tx1.scale(0.5, 0.5);

        g2d.setTransform(tx1);
        g2d.fillRect(0, 0, 80, 50);

        AffineTransform tx2 = new AffineTransform();
        tx2.translate(170, 20);
        tx2.scale(1.5, 1.5);

        g2d.setTransform(tx2);
        g2d.fillRect(0, 0, 80, 50);

    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Scaling");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Scale());
        frame.setSize(330, 160);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
We have a rectangle. First we scale it down and then we scale it up a bit. 
</p>

<pre class="explanation">
AffineTransform tx2 = new AffineTransform();
tx2.translate(170, 20);
tx2.scale(1.5, 1.5);
</pre>

<p>
Another scaling would be added to the first one. So we need to 
create and apply another affine transform. 
</p>

<img src="/img/gfx/java2d/scaling.png" alt="Scaling">
<div class="figure">Figure: Scaling</div>


<h2>Shearing</h2>

<p>
In the following example we perform shearing. We use the <code>share()</code> method. 
</p>

<div class="codehead">Scale.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Shear extends JPanel {

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;


        AffineTransform tx1 = new AffineTransform();
        tx1.translate(50, 90);

        g2d.setTransform(tx1);
        g2d.setColor(Color.green);
        g2d.drawRect(0, 0, 160, 50);

        AffineTransform tx2 = new AffineTransform();
        tx2.translate(50, 90);
        tx2.shear(0, 1);

        g2d.setTransform(tx2);
        g2d.setColor(Color.blue);

        g2d.draw(new Rectangle(0, 0, 80, 50));

        AffineTransform tx3 = new AffineTransform();
        tx3.translate(130, 10);
        tx3.shear(0, 1);

        g2d.setTransform(tx3);
        g2d.setColor(Color.red);
        g2d.drawRect(0, 0, 80, 50);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Shearing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Shear());
        frame.setSize(330, 270);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
In this example, we draw three rectlangles in three different colors. 
They form a structure. 
Two of them are sheared.
</p>

<pre class="explanation">
tx2.shear(0, 1);
</pre>

<p>
The two parameters are multipliers by which coordinates  are shifted 
in the direction of the x and y axis.
</p>


<img src="/img/gfx/java2d/shearing.png" alt="Shearing">
<div class="figure">Figure: Shearing</div>


<h2>Donut</h2>

<p>
In the following example we create an complex shape by rotating an ellipse.
</p>

<div class="codehead">Donut.java</div>
<pre class="code">
package com.zetcode;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Donut extends JPanel {


    public void paint(Graphics g) {

        super.paint(g);

        Graphics2D g2 = (Graphics2D)g;

        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);


        rh.put(RenderingHints.KEY_RENDERING,
               RenderingHints.VALUE_RENDER_QUALITY);

        g2.setRenderingHints(rh);

        Dimension size = getSize();
        double w = size.getWidth();
        double h = size.getHeight();

        Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);
        g2.setStroke(new BasicStroke(1));
        g2.setColor(Color.gray);


        for (double deg = 0; deg &lt; 360; deg += 5) {
            AffineTransform at =
                AffineTransform.getTranslateInstance(w / 2, h / 2);
            at.rotate(Math.toRadians(deg));
            g2.draw(at.createTransformedShape(e));
        }
    }


    public static void main(String[] args) {

        JFrame frame = new JFrame("Donut");
        frame.add(new Donut());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(370, 320);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
In this example, we create a donut.
</p>


<pre class="explanation">
Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.gray);
</pre>

<p>
In the beginning there was an ellipse. 
</p>

<pre class="explanation">
for (double deg = 0; deg &lt; 360; deg += 5) {
    AffineTransform at =
        AffineTransform.getTranslateInstance(w / 2, h / 2);
    at.rotate(Math.toRadians(deg));
    g2.draw(at.createTransformedShape(e));
}
</pre>

<p>
After several rotations, there is a donut. 
</p>


<img src="/img/gfx/java2d/donut.png" alt="Donut">
<div class="figure">Figure: Donut</div>


<p>
In this part of the Java 2D tutorial, we have talked about transformations.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified October 26, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

